package com.cgc.venus.server.core.k8s.impl;

import com.cgc.venus.server.core.bean.response.VenusResponseStatus;
import com.cgc.venus.server.core.exception.VenusException;
import com.cgc.venus.server.core.k8s.inter.K8sManageService;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.*;
import io.fabric8.kubernetes.api.model.apps.DaemonSet;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentStrategy;
import io.fabric8.kubernetes.api.model.apps.DeploymentStrategyBuilder;
import io.fabric8.kubernetes.api.model.apps.ReplicaSet;
import io.fabric8.kubernetes.api.model.autoscaling.v1.HorizontalPodAutoscaler;
import io.fabric8.kubernetes.api.model.autoscaling.v1.HorizontalPodAutoscalerBuilder;
import io.fabric8.kubernetes.api.model.autoscaling.v1.HorizontalPodAutoscalerList;
import io.fabric8.kubernetes.api.model.autoscaling.v1.HorizontalPodAutoscalerSpec;
import io.fabric8.kubernetes.api.model.batch.Job;
import io.fabric8.kubernetes.api.model.extensions.*;
import io.fabric8.kubernetes.api.model.networking.NetworkPolicy;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by 业哥 on 2017/11/16.
 * kubernetes 应用管理-接口实现
 */

@org.springframework.stereotype.Service
public class K8sManageServiceImpl implements K8sManageService {
    @Autowired
    private KubernetesClient k8sClient;

    @Override
    public KubernetesClient getK8sClient() {
        return k8sClient;
    }

    @Override
    public Namespace createNamespaceByYaml(String yamlContent) throws VenusException {
        Namespace namespace = k8sClient.namespaces().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return namespace;
    }

    @Override
    public Node createNodeByYaml(String yamlContent) throws VenusException {
        Node node = k8sClient.nodes().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return node;
    }

    @Override
    public Pod createPodByYaml(String yamlContent) throws VenusException {
        Pod pod = k8sClient.pods().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return pod;
    }

    @Override
    public Service createServiceByYaml(String yamlContent) throws VenusException {
        Service service = k8sClient.services().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return service;
    }

    @Override
    public PersistentVolume createPersistentVolumeByYaml(String yamlContent) throws VenusException {
        PersistentVolume persistentVolume = k8sClient.persistentVolumes().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return persistentVolume;
    }

    @Override
    public PersistentVolumeClaim createPersistentVolumeClaimByYaml(String yamlContent) throws VenusException {
        PersistentVolumeClaim persistentVolumeClaim = k8sClient.persistentVolumeClaims().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return persistentVolumeClaim;
    }

    @Override
    public Deployment createDeploymentByYaml(String yamlContent) throws VenusException {
        Deployment deployment = k8sClient.apps().deployments().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return deployment;
    }

    @Override
    public Secret createSecretByYaml(String yamlContent) throws VenusException {
        Secret secret = k8sClient.secrets().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return secret;
    }

    @Override
    public StatefulSet createStatefulSetByYaml(String yamlContent) throws VenusException {
        StatefulSet statefulSet = k8sClient.apps().statefulSets().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return statefulSet;
    }

    @Override
    public ServiceAccount createServiceAccountByYaml(String yamlContent) throws VenusException {
        ServiceAccount serviceAccount = k8sClient.serviceAccounts().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return serviceAccount;
    }

    @Override
    public ReplicaSet createReplicaSetByYaml(String yamlContent) throws VenusException {
        ReplicaSet replicaSet = k8sClient.apps().replicaSets().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return replicaSet;
    }

    @Override
    public ReplicationController createReplicationControllerByYaml(String yamlContent) throws VenusException {
        ReplicationController replicationController = k8sClient.replicationControllers().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return replicationController;
    }

    @Override
    public Job createJobByYaml(String yamlContent) throws VenusException {
        Job job = k8sClient.extensions().jobs().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return job;
    }

    @Override
    public Ingress createIngressByYaml(String yamlContent) throws VenusException {
        Ingress ingress = k8sClient.extensions().ingresses().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return ingress;
    }

    @Override
    public ConfigMap createConfigMapByYaml(String yamlContent) throws VenusException {
        ConfigMap configMap = k8sClient.configMaps().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return configMap;
    }

    @Override
    public HorizontalPodAutoscaler createHorizontalPodAutoscalerByYaml(String yamlContent) throws VenusException {
        HorizontalPodAutoscaler horizontalPodAutoscaler = k8sClient.autoscaling().v1().horizontalPodAutoscalers().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return horizontalPodAutoscaler;
    }

    @Override
    public NetworkPolicy createNetworkPolicyByYaml(String yamlContent) throws VenusException {
        NetworkPolicy networkPolicy = k8sClient.network().networkPolicies().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return networkPolicy;
    }

    @Override
    public DaemonSet createDaemonSetByYaml(String yamlContent) throws VenusException {
        DaemonSet daemonSet = k8sClient.apps().daemonSets().load(new ByteArrayInputStream(yamlContent.getBytes())).createOrReplace();
        return daemonSet;
    }

    /*
    * 19: 根据空间名,应用名称,获得deployment资源信息
    * @param namespace 应用空间
    * @param appNameKube 应用名称
    * */
    @Override
    public Deployment getDeployment(String namespace, String appNameKube) throws VenusException {
        Deployment deployment=k8sClient.apps().deployments().inNamespace(namespace).withName(appNameKube.trim()).get();
        //Deployment deployment = k8sClient.extensions().deployments().inNamespace(namespace).withName(appNameKube.trim()).get();
        return deployment;
    }

    /*
    * 20: 根据空间名称获得,statefulset 资源信息
    * @param namespace 应用空间
    * @param appNameKube 应用名称
    * */
    @Override
    public StatefulSet getStatefulSet(String namespace, String appNameKube) throws VenusException {
        StatefulSet statefulSet = k8sClient.apps().statefulSets().inNamespace(namespace).withName(appNameKube).get();
        return statefulSet;
    }

    /*
    * 21: 根据空间名称得到所有pod信息
    * @param namespace
    * */
    @Override
    public PodList getPodList(String namespace) throws VenusException {
        PodList podList = k8sClient.pods().inNamespace(namespace).list();
        return podList;
    }

    @Override
    public int horizontalScalingDeployment(String namespace, String appNameKube, int replicas) throws VenusException {
        Deployment deployment = k8sClient.apps().deployments().inNamespace(namespace).withName(appNameKube).scale(replicas);
        return deployment.getSpec().getReplicas().intValue();
    }

    @Override
    public int horizontalScalingStatefulSet(String namespace, String appNameKube, int replicas) throws VenusException {
        StatefulSet statefulSet = k8sClient.apps().statefulSets().inNamespace(namespace).withName(appNameKube).scale(replicas);
        return statefulSet.getSpec().getReplicas().intValue();
    }

    @Override
    public boolean updateDeployment(String namespace, String appNameKube, String targetImage) throws VenusException {
        Deployment deployment = k8sClient.apps().deployments().inNamespace(namespace).withName(appNameKube).get();
        // 获取原来应用的镜像
        List<Container> containerList = deployment.getSpec().getTemplate().getSpec().getContainers();
        List<Container> containerList1 = new ArrayList<Container>();
        for (Container container : containerList) {
            container.setImage(targetImage);
            containerList1.add(container);
        }
        // 重新设置
        deployment.getSpec().getTemplate().getSpec().setContainers(containerList1);
        Deployment deployment1 = k8sClient.apps().deployments().inNamespace(namespace).withName(appNameKube).createOrReplace(deployment);
        if (deployment1 != null) {
            return true;
        }
        return false;
    }

    @Override
    public boolean updateStatefunSet(String namespace, String appNameKube, String targetImage) throws VenusException {
        StatefulSet statefulSet = k8sClient.apps().statefulSets().inNamespace(namespace).withName(appNameKube).get();
        // 获取原来应用的镜像
        List<Container> containerList = statefulSet.getSpec().getTemplate().getSpec().getContainers();
        List<Container> containerList1 = new ArrayList<Container>();
        for (Container container : containerList) {
            container.setImage(targetImage);
            containerList1.add(container);
        }
        // 从新设置
        statefulSet.getSpec().getTemplate().getSpec().setContainers(containerList1);
        StatefulSet statefulSet1 = k8sClient.apps().statefulSets().inNamespace(namespace).withName(appNameKube).createOrReplace(statefulSet);
        if (statefulSet1 != null) {
            return true;
        }
        return false;
    }

    @Override
    public boolean updateDaemonSet(String namespace, String appNameKube, String targetImage) throws VenusException {
        DaemonSet daemonSet = k8sClient.apps().daemonSets().inNamespace(namespace).withName(appNameKube).get();
        List<Container> containerList = daemonSet.getSpec().getTemplate().getSpec().getContainers();
        List<Container> containerList1 = new ArrayList<Container>();
        for (Container container : containerList) {
            container.setImage(targetImage);
            containerList1.add(container);
        }
        // 从新设置
        daemonSet.getSpec().getTemplate().getSpec().setContainers(containerList1);
        DaemonSet daemonSet1 = k8sClient.apps().daemonSets().inNamespace(namespace).withName(appNameKube).createOrReplace(daemonSet);
        if (daemonSet1 != null) {
            return true;
        }
        return false;
    }

    /*
    * 27: 获取自动伸缩对象
    * @param namespace 应用所属空间名称
    * @param appNameKube 应用名称
    * */
    @Override
    public HorizontalPodAutoscaler getHorizontalPodAutoscaler(String namespace, String hpaName) throws VenusException {
        HorizontalPodAutoscaler horizontalPodAutoscaler = null;
        try {
            horizontalPodAutoscaler = k8sClient.autoscaling().v1().horizontalPodAutoscalers().inNamespace(namespace).withName(hpaName).get();
        } catch (Exception e) {
            return horizontalPodAutoscaler;
        }
        return horizontalPodAutoscaler;
    }

    /*
    * 29: 为当前应用,新增自动伸缩功能
    * @param namespace 应用所属空间名称
    * @param appNameKube 应用名称
    * @param minReplicas 最小实例数
    * @param maxReplicas 最大实例数
    * @param targetCpuPercent 目标cpu百分比
    * */
    @Override
    public boolean addHorizontalPodAutoscaler(String namespace, String appNameKube,String hpaName,int minReplicas, int maxReplicas, int targetCpuPercent) throws VenusException {
        Map<String,String> appMap = new HashMap<String,String>();
        appMap.put("app",appNameKube);
        HorizontalPodAutoscaler horizontalPodAutoscaler = new HorizontalPodAutoscalerBuilder()
                .withApiVersion("autoscaling/v1")
                .withNewMetadata()
                    .withName(hpaName)
                    .withNamespace(namespace)
                    .withLabels(appMap)
                .endMetadata()
                .withNewSpec()
                    .withNewScaleTargetRef()
                .withApiVersion("extensions/v1beta1")
                .withKind("Deployment")
                .withName(appNameKube)
                .endScaleTargetRef()
                .withMinReplicas(minReplicas)
                .withMaxReplicas(maxReplicas)
                .withTargetCPUUtilizationPercentage(targetCpuPercent)
                .endSpec()
                .build();
        HorizontalPodAutoscaler horizontalPodAutoscaler1 = k8sClient.autoscaling().v1().horizontalPodAutoscalers().inNamespace(namespace).createOrReplace(horizontalPodAutoscaler);
        if (horizontalPodAutoscaler1 != null) {
            return true;
        }
        return false;
    }

    /*
    * 30: 修改应用的自动伸缩参数
    * @param namespace 应用所属空间名称
    * @param appNameKube 应用名称
    * @param minReplicas 最小实例数
    * @param maxReplicas 最大实例数
    * @param targetCpuPercent 目标cpu百分比
    * */
    @Override
    public boolean editHorizontalPodAutoscaler(String namespace, String hpaName, int minReplicas, int maxReplicas, int targetCpuPercent) throws VenusException {
        // 先获取hpa对象
        HorizontalPodAutoscaler horizontalPodAutoscaler = getHorizontalPodAutoscaler(namespace,hpaName);
        if (horizontalPodAutoscaler != null) {
            // 重新设置参数
            HorizontalPodAutoscalerSpec spec = horizontalPodAutoscaler.getSpec();
            spec.setMinReplicas(minReplicas);
            spec.setMaxReplicas(maxReplicas);
            spec.setTargetCPUUtilizationPercentage(targetCpuPercent);
            horizontalPodAutoscaler.setSpec(spec);
            HorizontalPodAutoscaler hpa1 = k8sClient.autoscaling().v1().horizontalPodAutoscalers().inNamespace(namespace).createOrReplace(horizontalPodAutoscaler);
            if (hpa1 != null) {
                return true;
            }
        }
        return false;
    }

    /*
    * 31: 删除应用的自动伸缩功能
    * @param namespace 应用所属空间名称
    * @param appNameKube 应用名称
    * */
    @Override
    public boolean deleteHorizontalPodAutoscaler(String namespace, String hpaName) throws VenusException {
        boolean isDelete = k8sClient.autoscaling().v1().horizontalPodAutoscalers().inNamespace(namespace).withName(hpaName).delete();
        return isDelete;
    }

    /*
    * 删除deployment
    * */
    @Override
    public boolean deleteDeployment(String namespace, String appNameKube) throws VenusException {
        return k8sClient.extensions().deployments().inNamespace(namespace).withName(appNameKube).delete();
    }

    /*
    * 删除 statefulset
    * */
    @Override
    public boolean deleteStatefulSet(String namespace, String appNameKube) throws VenusException {
        return k8sClient.apps().statefulSets().inNamespace(namespace).withName(appNameKube).delete();
    }

    /*
    * 删除daemonset
    * */
    @Override
    public boolean deleteDaemonSet(String namespace, String appNameKube) throws VenusException {
        return k8sClient.extensions().daemonSets().inNamespace(namespace).withName(appNameKube).delete();
    }

    /*
    * 删除pod
    * */
    @Override
    public boolean deletePod(String namespace, String appNameKube) throws VenusException {
        return k8sClient.pods().inNamespace(namespace).withName(appNameKube).delete();
    }

    /*
    * 36: 获取pod 事件
    * */
    @Override
    public List<Event> getPodEvents(String namespace) throws VenusException {
        EventList eventList = k8sClient.events().inNamespace(namespace).list();
        List<Event> events = new ArrayList<Event>();
        if (eventList.getItems() != null) {
            events = eventList.getItems();
        }
        return events;
    }

    /*
   * 37: 根据标签,获取pod 列表
   * */
    @Override
    public PodList getPodListWithLabels(String namespace, String key, String value) throws VenusException {
        PodList podList = k8sClient.pods().inNamespace(namespace).withLabel(key,value).list();
        return podList;
    }

    @Override
    public DeploymentStrategy getDeploymentStrategy() throws VenusException {
        DeploymentStrategy deploymentStrategy = new  DeploymentStrategyBuilder()
                .withNewRollingUpdate()
                .withNewMaxSurge()
                .withIntVal(1)
                .endMaxSurge()
                .withNewMaxUnavailable()
                .withIntVal(1)
                .endMaxUnavailable()
                .endRollingUpdate()
                .build();
        return deploymentStrategy;
    }

    @Override
    public LocalObjectReference getLocalObjectReference(String refName) throws VenusException {
        LocalObjectReference localObjectReference = new LocalObjectReferenceBuilder()
                .withName(refName)
                .build();
        return localObjectReference;
    }

    @Override
    public Deployment createDployment(Deployment deployment,String namespace) throws VenusException {
        deployment = k8sClient.apps().deployments().inNamespace(namespace).create(deployment);
        return deployment;
    }

    @Override
    public Service createService(Service service, String namespace) throws VenusException {
        try {
            Service Service = k8sClient.services().inNamespace(namespace).create(service);
            return Service;
        }catch (Exception ex){
            ex.printStackTrace();
            throw new VenusException(VenusResponseStatus.K8S_EXCEPTION,ex.getMessage());
        }
    }

    @Override
    public Service createOrUpdateService(String namespace, Service service) throws VenusException {
        Service service1 = k8sClient.services().inNamespace(namespace).createOrReplace(service);
        return service1;
    }

    @Override
    public boolean deleteService(String serviceName, String namespace) throws VenusException {
        Service service = k8sClient.services().inNamespace(namespace).withName(serviceName).get();
        if (service != null) {
            // 删除
            return k8sClient.services().inNamespace(namespace).withName(serviceName).delete();
        }
        return false;
    }

    @Override
    public StatefulSet createStatefulSet(StatefulSet statefulSet, String namespace) throws VenusException {
        return k8sClient.apps().statefulSets().inNamespace(namespace).create(statefulSet);
    }

    @Override
    public Service getService(String namespace, String serviceName) throws VenusException {
        Service service = null;
        try {
            service = k8sClient.services().inNamespace(namespace).withName(serviceName).get();
        } catch (Exception e) {
            return null;
        }
        return service;
    }

    /*
    * 54: 创建ingress
    * */
    @Override
    public Ingress createIngress(String ingressName, String namespace,String appNamekube, String domainName, String serviceName, int port) throws VenusException {
        Map<String,String> annoMap = new HashMap<String,String>();
        annoMap.put("kubernetes.io/ingress.class","traefik");

        Map<String,String> appMap = new HashMap<String,String>();
        appMap.put("app",appNamekube);

        HTTPIngressPath httpIngressPath = new HTTPIngressPathBuilder()
                .withPath("/")
                .withNewBackend()
                    .withServiceName(serviceName)
                    .withNewServicePort()
                        .withIntVal(port)
                    .endServicePort()
                .endBackend()
                .build();

        // 规则
        IngressRule ingressRule = new IngressRuleBuilder()
                .withHost(domainName)
                .withNewHttp()
                    .withPaths(httpIngressPath)
                .endHttp()
                .build();

        Ingress ingress = new IngressBuilder()
                .withNewMetadata()
                    .withName(ingressName)
                    .withNamespace(namespace)
                    .withLabels(appMap)
                    .withAnnotations(annoMap)
                .endMetadata()
                .withNewSpec()
                    .withRules(ingressRule)
                .endSpec()
                .build();

        Ingress ingress1 = k8sClient.extensions().ingresses().create(ingress);
        return ingress1;
    }

    /*
   * 55: 得到service对象根据标签
   * */
    @Override
    public ServiceList getServiceListByLabels(Map<String, String> map, String namespace) throws VenusException {
        ServiceList serviceList = k8sClient.services().inNamespace(namespace).withLabels(map).list();
        return serviceList;
    }

    /*
   * 56: 删除service,根据标签
   * */
    @Override
    public boolean deleteServiceByLabels(Map<String, String> map, String namespace) throws VenusException {
        boolean flag = k8sClient.services().inNamespace(namespace).withLabels(map).delete();
        return flag;
    }

    /*
   * 57: 删除ingress 根据标签
   * */
    @Override
    public boolean deleteIngressByLabels(Map<String, String> map, String namespace) throws VenusException {
        IngressList ingressList = k8sClient.extensions().ingresses().inNamespace(namespace).withLabels(map).list();
        if (ingressList != null) {
            if (ingressList.getItems().size() > 0) {
                return k8sClient.extensions().ingresses().inNamespace(namespace).withLabels(map).delete();
            }
        }
        return true;
    }

    /*
   * 58: 删除高可用
   * */
    @Override
    public boolean deleteHPAByLabels(Map<String, String> map, String namespace) throws VenusException {

        HorizontalPodAutoscalerList horizontalPodAutoscalerList = k8sClient.autoscaling().v1().horizontalPodAutoscalers().inNamespace(namespace).withLabels(map).list();
        if (horizontalPodAutoscalerList != null) {
            if (horizontalPodAutoscalerList.getItems().size() > 0) {
                return k8sClient.autoscaling().v1().horizontalPodAutoscalers().inNamespace(namespace).withLabels(map).delete();
            }
        }
        return true;
    }

    @Override
    public Deployment createOrReplaceDeployment(Deployment deployment, String namespace) throws VenusException {
        return k8sClient.apps().deployments().inNamespace(namespace).createOrReplace(deployment);
    }

    @Override
    public boolean deleteIngressByName(String ingressName, String namespace) throws VenusException {
        return k8sClient.extensions().ingresses().inNamespace(namespace).withName(ingressName).delete();
    }

    /*
    * 得到ingress
    * */
    @Override
    public Ingress getIngress(String namespace, String ingressName) throws VenusException {
        Ingress ingress = k8sClient.extensions().ingresses().inNamespace(namespace).withName(ingressName).get();
        return ingress;
    }

    /*
    * 得到ingressList
    * */
    @Override
    public IngressList getIngressList(String namespace) throws VenusException {
        return k8sClient.extensions().ingresses().inNamespace(namespace).list();
    }

    @Override
    public Ingress createOrUpdateIngress(String namespace, Ingress newIngress) throws VenusException {
        Ingress ingress = k8sClient.extensions().ingresses().inNamespace(namespace).createOrReplace(newIngress);
        return ingress;
    }

    @Override
    public ServiceList getServiceList() throws VenusException {
        return k8sClient.services().list();
    }

    /*
    * 64: 根据命名空间得到服务list
    * */
    public ServiceList getServiceListByNamespace(String namespace) throws VenusException{
        return k8sClient.services().inNamespace(namespace).list();
    }


}